package org.lex.jdbc.url.persist.xml;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.lex.jdbc.url.DriverConfig;
import org.lex.jdbc.url.persist.AbstractDriverDaoImpl;
import org.lex.jdbc.url.persist.IDriverDao;

@SuppressWarnings("unchecked")
public class XmlDriverDaoImpl extends AbstractDriverDaoImpl implements
		IDriverDao, XmlDaoConstants, XmlEntityDao<DriverConfig> {

	private File driverConfigFile;
	private XmlDaoHelper<DriverConfig> helper = new XmlDaoHelper<DriverConfig>();

	public XmlDriverDaoImpl(File parentDirectory) {
		String fileName = IDriverDao.class.getPackage().getName()
				+ ".drivers.xml";
		this.driverConfigFile = new File(parentDirectory, fileName);
	}

	// ================================
	// implements IDriverDao
	// ================================
	@Override
	public List<DriverConfig> getUserDrivers() throws IOException {
		return helper.getAllEntities(this.driverConfigFile, this);
	}

	@Override
	public void saveDriver(DriverConfig driver) throws IOException {
		helper.save(this.driverConfigFile, this, driver);
	}

	@Override
	public void updateDriver(DriverConfig oldDriver, DriverConfig newDriver)
			throws IOException {
		this.helper.update(this.driverConfigFile, this, oldDriver,
				newDriver);
	}

	@Override
	public void deleteDriver(DriverConfig driver) throws IOException {
		this.helper.delete(this.driverConfigFile, this, driver);
	}

	// ================================
	// implements XmlEntityDao
	// ================================

	public void marshal(DriverConfig driver, Element driverElement) {
		driverElement.addAttribute("name", driver.getName());
		driverElement.addAttribute("className", driver.getClassName());
		driverElement.addAttribute("description", driver.getDescription());
		driverElement.addAttribute("website", driver.getWebsite());
		for (File file : driver.getClasspath()) {
			driverElement.addElement("Location")
					.setText(file.getAbsolutePath());
		}
	}

	@Override
	public DriverConfig unmarshal(Element driverElement) {
		DriverConfig dc = new DriverConfig();
		dc.setName(driverElement.attributeValue("name"));
		dc.setClassName(driverElement.attributeValue("className"));
		dc.setDescription(driverElement.attributeValue("description"));
		dc.setWebsite(driverElement.attributeValue("website"));
		for (Iterator<Element> locationElementIter = driverElement
				.elementIterator("Location"); locationElementIter.hasNext();) {
			dc.getClasspath().add(
					new File(locationElementIter.next().getTextTrim()));
		}
		return dc;
	}

	@Override
	public Iterator<Element> getEntityIterator(Document doc) {
		return doc.getRootElement().elementIterator("Driver");
	}

	@Override
	public Element createNewEntityElement(Document doc) {
		return doc.getRootElement().addElement("Driver");
	}
}
